
package com.zws.cucumber.glue;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.zws.cucumber.expr.ZwsExpr;
import com.zws.cucumber.util.colorfullog.ZwsColorfulLogger;
import com.zws.cucumber.util.colorfullog.ZwsPrintTableHelper;
import com.zws.cucumber.var.ZwsVar;
import io.cucumber.datatable.DataTable;
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.zws.cucumber.expander.ZwsStr.expand;

/**
 * author: zws
 */
public class ZwsCommonStepDef {

    private static final Logger logger = ZwsColorfulLogger.of(ZwsCommonStepDef.class);

    @Given("assert {word} match {string}")
    public void assertVariableMatch(String variableName, String value) {
        ZwsExpr.verify(variableName, expand(value), ZwsVar.get(variableName));
    }

    @Given("assert {word} match")
    public void assertVariableMatchByDocString(String variableName, String value) {
        assertVariableMatch(variableName, value);
    }

    @Given("assert that {string}")
    public void assertThat(String value) {
        assertVariableMatch("", value);
    }

    @Given("assert that")
    public void assertThatByDocString(String value) {
        assertVariableMatch("", value);
    }

    @Given("extract value from {string}")
    public void extractValueFrom(String raw, DataTable table) {
        if (StringUtils.isNotEmpty(raw)) {
            String expanded = expand(raw);
            if (StringUtils.isNotEmpty(expanded)) {
                for (List<String> pair : table.cells()) {
                    String jsonPath = pair.get(0);
                    String variableName = pair.get(1);

                    JsonPath jp = JsonPath.compile(jsonPath);
                    Object val = jp.read(expanded, Configuration.builder().options(Option.SUPPRESS_EXCEPTIONS).build());
                    ZwsVar.put(variableName, val);
                }
            } else {
                logger.warn("expanded is empty, skip");
            }
        } else {
            logger.warn("raw is empty, skip");
        }
    }

    @And("sleep {int} seconds")
    public void sleepSeconds(int seconds) {
        logger.debug("sleep for " + seconds + "s.");
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @And("sleep {string} seconds")
    public void sleepSeconds(String seconds) {
        logger.debug("sleep for " + seconds + "s.");
        try {
            TimeUnit.SECONDS.sleep(Long.parseLong(expand(seconds)));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Given("sleep {int} milliseconds")
    public void sleepMilliSeconds(int ms) {
        logger.debug("sleep for " + ms + "ms.");
        try {
            TimeUnit.MILLISECONDS.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Given("sleep {string} milliseconds")
    public void sleepMilliSeconds(String ms) {
        logger.debug("sleep for " + ms + "ms.");
        try {
            TimeUnit.MILLISECONDS.sleep(Long.parseLong(expand(ms)));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
